//: Playground - noun: a place where people can play

import UIKit

//: # swfit 读书笔记

//: ## 析造过程 就是init 方法

//: ### 存储属性的初始赋值 : 就是在初始化方法里面给属性赋值
struct Fahrenheit{
    var fahren:Double
    init() {
        fahren = 100.0
    }
}

//: ### 自定义构造过程
//: ### 内部参数和外部参数
//: 系统自动生成和内部参数一致的外部参数

class Color{
    let red,yellow,blue:Double
    
    init(red:Double,yellow:Double,blue:Double) {
        self.red = red
        self.yellow = yellow
        self.blue = blue
    }
    
    init(white: Double) {
        self.red = white
        self.yellow = white
        self.blue = white
    }
    
    //:如果你不希望为构造器的某个参数提供外部名字，你可以使用下划线(_)来显式描述它的外部名
    init(_ black:Double) {
        self.red = black
        self.yellow = black
        self.blue = black
    }
    
    
}
let magenta = Color (red: 1.0, yellow: 2.0, blue: 3.0)
let halfGray = Color (white: 10.0)
let newCloler = Color (100.0)


//: ### 构造过程中常量属性的初始值 : 对于类的实例来说，它的常量属性只能在定义它的类的构造过程中修改；不能在子类中修改
class ConstantClass{
    let constantNum:Int
    let constantNumOne:Int = 1000
    
    
    init(num:Int) {
        self.constantNum = num
         // self.constantNumOne = num 这个就不能改了，因为你初始化了
    }
}

let constantCls = ConstantClass (num: 100)



//: ### 默认构造器：自己不写构造器 系统自动生成一个(隐式的)

//: ### 值类型的构造器代理: (结构体和枚举)构造器可以通过调用其它构造器来完成实例的部分构造过程。这一过程称为构造器代理，它能减少多个构造器间的代码重复
//: ### note: 某个值类型定义了一个自定义的构造器，你将无法访问到默认构造器（如果是结构体，还将无法访问逐一成员构造器）
//: ### note:假如你希望默认构造器、逐一成员构造器以及你自己的自定义构造器都能用来创建实例，可以将自定义的构造器写到扩展（extension）中

struct Size {
    var width = 0.0, height = 0.0
}
struct Point {
    var x = 0.0, y = 0.0
}

struct Rect {
    var origin = Point()
    var size = Size()
    init() {}
    init(origin: Point, size: Size) {
        self.origin = origin
        self.size = size
    }
    init(center: Point, size: Size) {
        let originX = center.x - (size.width / 2)
        let originY = center.y - (size.height / 2)
        self.init(origin: Point(x: originX, y: originY), size: size)
    }
}

//: ### 类的继承和构造过程
//: ### Swift 为类类型提供了两种构造器 "指定构造器"和"便利构造器"。
//: ### 便利构造器 : 便利构造器来调用同一个类中的指定构造器。 需要在init关键字之前放置convenience关键字
//: ### note  1.指定构造器必须总是向上代理   2.便利构造器必须总是横向代理
class Food{
    var name:String
    
    init(name:String) {
        self.name = name
    }
    
    convenience init(){
        self.init(name: "[未知]")
    }
}

class RecipeIngredient:Food{
    var quantity:Int
    init(name:String,quantity:Int){
        self.quantity = quantity;
        super.init(name: name)
    }
    
    convenience override init(name: String) {
        self.init(name: name, quantity: 1)
    }
}

class ShoppingListItem:RecipeIngredient{
    var purchased = false
    
    var description:String{
        var output = "\(quantity)*\(name)）"
        output += purchased ? "对":"错"
        return output
    }
    
}

//: ### 可失败构造器
class Animal {
    var species: String
    
    init() {
        self.species = ""
    }
    
    init?(species: String) {
        if species.isEmpty { return nil }
        self.species = species
    }
     
}

let someCreature = Animal(species: "Giraffe")
if let giraffe = someCreature {
    print("An animal was initialized with a species of \(giraffe.species)")
}

//: ### 重写一个可失败的构造器
class cat:Animal{
    
    override init(species: String){
        super.init() //: 这个调用的是默认构造器
        if species.isEmpty {
            self.species = "123"
        }else{
            self.species = species
        }
    }
    
}

//: ### 必要构造器
//: ### 构造器前添加required修饰符表明所有该类的子类都必须实现该构造器
//: ### 如果子类继承的构造器能满足必要构造器的要求，则无须在子类中显式提供必要构造器的实现。
class SomeClass {
    required init() {
        // 构造器的实现代码
    }
}
//: ### 通过闭包或函数设置属性的默认值 : 就是在一个闭包里面初始化而已
//: ### 如果你使用闭包来初始化属性，请记住在闭包执行时，实例的其它部分都还没有初始化。这意味着你不能在闭包里访问其它属性，即使这些属性有默认值。同样，你也不能使用隐式的self属性，或者调用任何实例方法。

class SomeClassBlock {
    let someProperty: String = {
        return "zzp"
    }()
}

//: # swfit 读书笔记

//: ## 析构过程
//: ### 析构器只适用于类类型 就是 deinit 也就是 oc dealloc

class  deinitClass{
    deinit {
        // 执行析构过程
    }
}


